package mailsystem;

import java.util.ArrayList;
import java.util.List;

import mailsystem.audio.AudioPlayer;
import mailsystem.audio.AudioRecorder;
import mailsystem.states.AddContactStatus;
import mailsystem.states.ChangeGreetingStatus;
import mailsystem.states.ChangeNameStatus;
import mailsystem.states.ChangePassCodeStatus;
import mailsystem.states.ConnectedStatus;
import mailsystem.states.MailBoxMenuStatus;
import mailsystem.states.MessageMenuStatus;
import mailsystem.states.RecordingAudioStatus;
import mailsystem.states.RecordingStatus;
import mailsystem.states.ResendStatus;
import mailsystem.states.State;


/**
 * Connects a phone to the mail system. The purpose of this class is to keep
 * track of the state of a connection, since the phone itself is just a source
 * of individual key presses.
 */
public class Connection {
	/**
	 * Construct a Connection object.
	 * 
	 * @param s a MailSystem object
	 * @param theRecorder the audio recorder
	 * @param player the audio player
	 * @param p
	 *            a Telephone object
	 */
	public Connection(MailSystem s, AudioPlayer thePlayer, AudioRecorder theRecorder) {
		system = s;
		phones = new ArrayList<Telephone>();
		player = thePlayer;
		recorder = theRecorder;
	}

	/**
	 * Respond to the user's pressing a key on the phone touchpad
	 * 
	 * @param key
	 *            the phone key pressed by the user
	 */
	public void dial(String key) {
		state.runAction(this, key);
	}

	/**
	 * Record voice.
	 * 
	 * @param voice
	 *            voice spoken by the user
	 */
	public void record(String voice) {
		if (isRecording() ||  isChangeNameStatus())
			currentRecording += voice;
	}

	/**
	 * The user hangs up the phone.
	 */
	public void hangup() {
		if (isRecording())
			currentMailbox.addMessage(new Message(currentRecording, 0, false));
		else if ( isRecordingAudio())
		{
			stopRecording();
			currentMailbox.addMessage(new Message(currentRecording, 0, true));
		}
		resetConnection();
	}
	
	public void start()
	{
		resetConnection();
		for (Telephone p : phones) {
			p.run(this);
		}
	}

	/**
	 * Reset the connection to the initial state and prompt for mailbox number
	 */
	private void resetConnection() {
		currentRecording = "";
		accumulatedKeys = "";
		state = CONNECTED;
		speakAllPhones(TelephoneResources.INITIAL_PROMPT, TelephoneResources.INITIAL_PROMPT_AUDIO);
	}

	public void speakAllPhones(String message, String audiomessage) {
		for (Telephone p : phones) {
			p.speak(message);
		}
		if ( audiomessage != null )
			player.playSound(audiomessage);
	}

	public void showDisplayAllPhones(String message) {
		for (Telephone p : phones) {
			p.showDisplay(message);
		}
	}
	
	public static final State CONNECTED = new ConnectedStatus();
	public static final State RECORDING = new RecordingStatus();
	public static final State MAILBOXMENU = new MailBoxMenuStatus();
	public static final State MESSAGEMENU = new MessageMenuStatus();
	public static final State CHANGEPASSCODE = new ChangePassCodeStatus();
	public static final State CHANGEGREETING = new ChangeGreetingStatus();
	public static final State CHANGENAME = new ChangeNameStatus();
	public static final State RESEND = new ResendStatus();
	public static final State ADDCONTACT = new AddContactStatus();
	public static final State RECORDINGAUDIO = new RecordingAudioStatus();
	

	public boolean isConnected() {
		return state == CONNECTED;
	}

	public boolean isRecording() {
		return state == RECORDING;
	}
	
	public boolean isRecordingAudio()
	{
		return state == RECORDINGAUDIO;
	}

	public boolean isMailBoxMenuStatus() {
		return state == MAILBOXMENU;
	}

	public boolean isMessageMenuStatus() {
		return state == MESSAGEMENU;
	}

	public boolean isChangePassCodeStatus() {
		return state == CHANGEPASSCODE;
	}

	public boolean isChangeGreetingStatus() {
		return state == CHANGEGREETING;
	}
	
	public boolean isChangeNameStatus() {
		return state == CHANGENAME;
	}

	public int getPhonesCount() {
		return phones.size();
	}

	public void addPhone(Telephone phone) {
		phones.add(phone);
	}

	private MailSystem system;
	private Mailbox currentMailbox;
	private String currentRecording;
	private String accumulatedKeys;
	private State state;
	private List<Telephone> phones;
	private AudioPlayer player;
	private AudioRecorder recorder;

	public MailSystem getSystem() {
		return system;
	}

	public Mailbox getCurrentMailbox() {
		return currentMailbox;
	}

	public void setCurrentMailbox(Mailbox currentMailbox) {
		this.currentMailbox = currentMailbox;
	}

	public String getCurrentRecording() {
		return currentRecording;
	}
	
	public void setCurrentRecording(String currentRecording) {
		this.currentRecording = currentRecording;
	}

	public String getAccumulatedKeys() {
		return accumulatedKeys;
	}
	
	public void setAccumulatedKeys(String accumulatedKeys) {
		this.accumulatedKeys = accumulatedKeys;
	}

	public void setState(State s) {
		state = s;
	}
	
	public void beginRecording()
	{
		currentRecording = recorder.getNewAudioFileName();
		recorder.prepareRecord(currentRecording);
		Thread thread = new Thread(recorder);
		thread.start();
	}
	
	public void stopRecording()
	{
		recorder.stopRecording();
	}
}
